import java.util.Arrays;

/**
 * Created with IntelliJ IDEA
 * Description:顺序表-严谨
 * User:恋恋
 * Date:2022-10-20
 * Time:13:07
 */
public class MyArrayList {


    public int[] elem;

    public int usedSize;//0

    //默认容量

    private static final int DEFAULT_SIZE = 10;//static：数组属于类，不属于对象，final：不可修改数据


    public MyArrayList() {

        this.elem = new int[DEFAULT_SIZE];

    }


    /**
     * 打印顺序表:该方法并不是顺序表中的方法，为了方便看测试结果给出的
     * <p>
     * 根据usedSize判断即可
     */

    public void display() {
        if(isEmpty()==false){
            throw new NullException("数组空异常");
        }

        for (int i = 0; i < this.size(); i++) {
            System.out.print(this.elem[i] + " ");
        }
        System.out.println();
    }


    // 新增元素,默认在数组最后新增

    public void add(int data) {

        //1、检查当前的顺序表是不是满了？
        if (isFull()) {
            //2、如果满了就要扩容,扩容成原来的两倍
            this.elem= Arrays.copyOf(this.elem,2*this.elem.length);

            //throw new IndexOutOfException("数组越界访问");//throw就需要catch
        }
        this.elem[this.size()] = data;
        this.usedSize++;
    }


    /**
     * 判断当前的顺序表是不是满的！
     *
     * @return true:满   false代表空
     */

    public boolean isFull() {
//        if(this.size()>=this.elem.length){
//            return true;
//        }
//        return false;
        return this.size()>=this.elem.length;
    }

    /**
     * 判断访问的下标是否正确
     * @param pos
     * @return
     */

    private boolean checkPosInAdd(int pos) {
        //下标数字小于0或者大于等于目前长度
        if(pos<0||pos>=size()){

            throw new IndexOutOfException("下标访问异常");
        }

        return true;//合法

    }


    /**
     *  在 pos 位置新增元素
     *  漏：如果Pos下标不合法，那么就会抛出一个PosWrongFullException
     * @param pos
     * @param data
     */

//异常声明throws：处在方法声明中参数列表后，当方法中抛出运行时异常，用户不想处理该异常，借此throws将异常抛出给方法的调用者来处理。
    public void add(int pos, int data) throws IndexOutOfException {
       //不能满的时候添加元素
        if(isFull()){
            System.out.println("满了");
            throw new IndexOutOfException("数组已经满了，不能再添加了");
        }
       //不合法下标--因为是条件，所以可以添加到最后一个位置上
        if(pos<0||pos>size()){
            throw new IndexOutOfException("下标不合法");
        }
//        //特殊位置--就在末尾加
//        if()
//         不能隔着存入元素-判断下标是否合理--发现这个代码也包含了特殊位置末尾
        //pos一定是合法的
        //1、开始挪动数据
        for (int i = size()-1; i >=pos; i--) {
            this.elem[i+1]=this.elem[i];
        }
//        int i=size()-1;
//        while(i>pos){
//            this.elem[i]=this.elem[i+1];
//            i--;
//        }
        //2、插入数据
        this.elem[pos]=data;
        //3、总数据加加
        this.usedSize++;
        //先移动后添加


    }

    /**
     * 判定是否包含某个元素
     * @param toFind
     * @return
     */

    public boolean contains(int toFind) {
        //万一要是数组为空怎么办——会发生空异常

        if(isEmpty()==false){
            throw new NullException("数组为空");
        }

        for (int i = 0; i < this.size(); i++) {
            if(this.elem[i]==toFind){
                System.out.println("找到了，在第"+(i+1)+"个");
                return true;
            }
        }


        return false;

    }

    // 查找某个元素对应的位置

    public int indexOf(int toFind) {
//首先判断数组不能为空
        if(isEmpty()==false){
            throw new NullException("数组为空");
        }
        for (int i = 0; i < size(); i++) {
            if(this.elem[i]==toFind){
                return i+1;
            }
        }
        return -1;

    }


    // 获取 pos 位置的元素

    public int get(int pos) {
        //数组是否为空
        if(isEmpty()==false){
            throw new NullException("数组为空");
        }
        //访问下标位置是否合法--这里是访问，因此当下标等于数组长度时，也不可以
        if(checkPosInAdd(pos)==false){
            throw new IndexOutOfException("下标不合法");
        }

        return this.elem[pos];


    }

    /**
     * 判断数组不为空
     * true 不空      false 空
     * @return
     */

    private boolean isEmpty() {
        if(this.size()==0){
            return false;
        }
        return true;

    }

    // 给 pos 位置的元素设为【更新为】 value

    public void set(int pos, int value) {
//数组是否为空
        if(isEmpty()==false){
            throw new NullException("数组为空");
        }
        //访问下标位置是否合法--这里是访问，因此当下标等于数组长度时，也不可以
        if(checkPosInAdd(pos)==false){
            throw new IndexOutOfException("下标不合法");
        }
        this.elem[pos]=value;

    }


    /**
     * 删除第一次出现的关键字key
     *
     * @param key
     */

    public void remove(int key) {
        //判断是否为空
        if(isEmpty()==false){
            throw new NullException("数组为空,无法删除");
        }
        //第一种方法
//        //先找到在哪里，然后再先移
//        int i = 0;
//        for (i = 0; i < size(); i++) {
//            if(this.elem[i]==key){
//                break;//找到就退出来
//            }
//        }
//        //说明已经找到了
//        if(i<size()) {
//            for (int j = i; j < size() - 1; j++) {//限制条件是size()-1,因为如果是限制条件是size(),数组遍历到最后一个元素，就会发生数组越界，
//                //当删除的是最后一个元素，这个代码就不行
//                this.elem[j] = this.elem[j + 1];
//            }
//            this.usedSize--;
//
//        }
//        //特殊位置：删除最后一个元素
//        if(i==size()-1){
//            this.usedSize--;
//        }
//
          //第二种方法
        int index=this.indexOf(key);
        if(index==-1){
            System.out.println("没有这个数字");
            return;//无返回值
        }
        for(int i=index;i<this.size()-1;i++){
            this.elem[i]=this.elem[i+1];
        }
        this.usedSize--;
    }


     //获取顺序表长度

    public int size() {

return this.usedSize;
    }
    // 清空顺序表

    public void clear() {
this.usedSize=0;
//如果数组是引用类型的，就需要一个一个NULL
//        for (int i = 0; i < size(); i++) {
//            this.elem[i]=null;
//        }

    }
}